<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
</body>
</html>
<script>
//通过node来运行代码 接下来在 浏览器运行代码 需要重新创建项目 

//搭建浏览器开发环境步骤  
    //1 建立号文件夹后 打开vscode 把文件夹拉到编辑器里 打开终端 运行 npm init -y 创建package.json
    //2 生成文件后 接着在终端运行tsc -init 生成tsconfig.json文件     (坑 搭建环境时 目录不能用中文的)
    //3 新建src和build文件夹 再建一个index.html文件 
    //4 在src目录下 新建一个page.ts文件 这就是我们编写的ts文件了 
    //5 配置tsconfig.json文件 设置outDir 和 rootDir(代码15左右) 也就是设置需要编译的文件目录 和编译号的文件目录 
    //6 再编写index.html 引入<script src="./build/page.js">/script>   (注意现在还没有生成page.js文件)
    //7 再编写page.ts文件 加入一句console.log("常东东") 再在控制台输出tsc 生成page.js文件
    //8 再到浏览器查看index.html 按f12 可以看到常东东 说明搭建ok了  
        /*这是目录解构 
            djhj
                build
                    page.js
                src
                    page.ts
                    index.html
                    package.json
                    tsconfig.json        
        */

//没有命名空间时的问题  
    //先看代码 用类的形式在index.html中实现header content Footer部分 类似常说的模板 
    //在page.ts 文件里面写出下面代码   
    class Header {
    constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Header";
        document.body.appendChild(elem);
    }
    }

    class Content {
    constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Content";
        document.body.appendChild(elem);
    }
    }

    class Footer {
    constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Footer";
        document.body.appendChild(elem);
    }
    }

    class Page {
    constructor() {
        new Header();
        new Content();
        new Footer();
    }
    }
    // 写完之后 tsc编译一下 然后修改index.html文件 在<body>标签引入<script>标签 并实例化Page 代码如下
    <body>
        <script>new Page();</script>
    </body>
    //到浏览器预览 对应的 三句话(模块)展示出来了
    //注意了 这样写 全部都是全局变量 (通过查看 ./build/page.js文件可以看出来全部时var声明的变量)
    //过多的全局变量会让我们的代码变得 不可维护 
    /*这时候在浏览器控制台中 分别输出Header Content Footer 和Page 这时候可以拿到对应的变量的 说明他们都是全局变量*/
    /*理想代码是 只要有Page这个全局变量就足够了 剩下的可以模块化封装起来 不暴露全局 */

//命名空间的使用 
    //命名空间这个语法 类似编程中常说的模块化思想 
    /*比如webpack打包时 每个模块有自己的环境 不会污染其他模块 不会有全局变量产生 是类似而不是相同 */
    
    //命名空间声明关键字namespace 比如声明一个namespace Home 需要暴露出去 可以使用export关键词 
    //这样只有暴露出去的类是全局的 其他的不会成为全局污染 修改代码如下   
    namespace Home {
    class Header {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Header";
        document.body.appendChild(elem);
        }
    }

    class Content {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Content";
        document.body.appendChild(elem);
        }
    }

    class Footer {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Footer";
        document.body.appendChild(elem);
        }
    }

    export class Page {
        constructor() {
        new Header();
        new Content();
        new Footer();
        }
    }
    }    
    //ts代码写完后 再到index.html文件中进行修改 用命名空间形式进行调用 
    // OK后 tsc编译一下 (当然你也可以tsc -w进行监视一下 只要有改变 就会重新编译 )
    new Home.Page();
    /*再到浏览器中查看，看到现在就只有Home.Page是在控制台可以得到的，其他的Home.Header...这些都是得不到的，说明只有Home.Page是全局的，其他的都是模块化私有的。
      这就是 ts给我们提供的类似模块化开发的语法 好处让全局变量减少很多 实现基本封装 减少全局变量的污染 
    */

//深入命名空间 namespace  
    //用命名空间实现组件化 
    //上面的代码实现了模块化和全局变量的污染 实际工作中更细致 会单独写一个components 然后进行组件化 
    // 在src目录下新建一个文件夹 compoenent.ts 编写代码如下 
    namespace Components {
    export class Header {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Header";
        document.body.appendChild(elem);
        }
    }

    export class Content {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Content";
        document.body.appendChild(elem);
        }
    }

    export class Footer {
        constructor() {
        const elem = document.createElement("div");
        elem.innerText = "This is Footer";
        document.body.appendChild(elem);
        }
    }
    }
    //注意 我每个类calss 都使用了export导出 导出后就可以在page.ts中只用这些组件了 
    //比如这样使用 代码如下 
    namespace Home {
    export class Page {
        constructor() {
        new Components.Header();
        new Components.Content();
        new Components.Footer();
        }
    }
    }
    //这时候你可以使用tsc进行重新编译，但在预览时，你会发现还是会报错，
    //找不到Components,想解决这个问题，我们必须要在index.html里进行引入components.js文件
    <script src="./build/page.js"></script>
    <script src="./build/components.js"></script>   
    //这样才可以正常的出现效果。
    //但这样引入太麻烦了，可不可以像webpack一样，只生成一个文件那？那答案是肯定的。


// 多文件编译成一个文件 
    //直接打开tsconfig.json文件，然后找到outFile配置项，这个就是用来生成一个文件的设置，
    //但是如果设置了它，就不再支持"module":"commonjs"设置了，我们需要把它改成"module":"amd",然后在去掉对应的outFile注释，设置成下面的样子。
    {
     "outFile": "./build/page.js"
    }
    //配置好后，删除掉build下的js文件，然后用tsc进行再次编译。
    //然后删掉index.html文件中的component.js,在浏览器里还是可以正常运行的。


//子命名空间 
    //也就是说在命名空间里 再写一个命名空间 比如再components.ts文件修改代码如下 
    namespace Components {
    export namespace SubComponents {
        export class Test {}
    }
    //someting ...
    }
   //写完后在控制台再次编辑tsc，然后你在浏览器中也是可以查到这个命名空间的Components.SubComponents.Test(需要刷新页面后才会显示)。






    



























































































</script>